package main

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

type Coupon struct {
	CouponID       string `json:"coupon_id"`       // 券ID
	CouponType     string `json:"coupon_type"`     // 券类型 用于住宿或电商
	GetCouponTime  string `json:"get_coupon_time"` // 领取时间
	UsedTime       string `json:"used_time"`       // 使用时间
	DeadLine       string `json:"dead_line"`       // 券失效时间
	DiscountAmount int    `json:"discount_amount"` // 抵扣金额
	UseCondition   int    `json:"use_condition"`   // 使用条件（满500）
	Status         string `json:"status"`          // 消费券状态 1-领取未使用 2-领取并使用 3-商家向政府申请补助后的消费券状态 4-券过期

	UserID     string `json:"user_id"`     // 用户ID
	BusinessID string `json:"business_id"` // 商家ID
}

type CouponCondition struct {
	CouponValue   int `json:"coupon_value"`    // 消费券面值
	CouponNum     int `json:"coupon_num"`      // 消费券总数
	CouponUsed    int `json:"coupon_used"`     // 已使用消费券 2
	CouponUnused  int `json:"coupon_unused"`   // 已领取但未使用消费券 1
	CouponEnd     int `json:"coupon_end"`      // 商家向政府部门申请补助 3
	CouponTimeOut int `json:"coupon_time_out"` // 已领取并过期的消费券 4
}

var (
	Coupon1 CouponCondition
	Coupon2 CouponCondition
	Coupon3 CouponCondition
	Coupon4 CouponCondition
	Coupon5 CouponCondition
	Coupon6 CouponCondition

	IsUseEvent bool
)

func (c *Coupon) Init(stub shim.ChaincodeStubInterface) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	fmt.Println("into Init")
	_, args := stub.GetFunctionAndParameters()
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1 args to Init")
	}
	switch strings.ToLower(args[0]) {
	case "false":
		IsUseEvent = false
	case "true":
		IsUseEvent = true
	default:
		//IsUseEvent = false
		return shim.Error(fmt.Sprintf("Invalid ChainCode Init args : %s", args[0]))
	}
	return shim.Success([]byte("Init function success"))
}

func (c *Coupon) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	functions, args := stub.GetFunctionAndParameters()
	switch strings.ToLower(functions) {
	case "createcoupon":
		return c.CreateCoupon(stub, args)
	//case "receivecoupon":
	//	return c.ReceiveCoupon(stub, args)
	case "findcouponbyid":
		return c.FindCouponByID(stub, args)
	case "usecoupon":
		return c.UseCoupon(stub, args)
	case "settlementwithgov":
		return c.SetlemetntWithGov(stub, args)
	//case "gettotalbalance":
	//	return c.GetTotalBalance(stub, args)
	case "userunspendcoupon":
		return c.UserUnspendCoupon(stub, args)
	case "userspendcoupon":
		return c.UserSpendCoupon(stub, args)
	case "getbuinesscouponinfo":
		return c.GetBuinessCouponInfo(stub, args)
	case "querycouponnum":
		return c.QueryCouponNum(stub, args)
	case "updatecoupontimeout":
		return c.UpdateCouponTimeout(stub, args)
	default:
		return shim.Error(fmt.Sprintf("Invalid ChainCode Function : %s", functions))
	}
}

//CreateCoupon 生成消费券 接收一个参数 就是结构体Coupon的变量
func (c *Coupon) CreateCoupon(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	var coupon Coupon
	fmt.Println("into CreateCoupon")
	tmp := args[0]
	//tmp := "{\"couponID\":\"123\",\"couponType\":\"dianshang\",\"createdDateTime\":\"20200101\",\"usedTime\":\"\",\"deadLine\":\"20201230\",\"discountAmount\":\"5\",\"useCondition\":\"100\",\"status\":\"0\",\"userID\":\"\",\"businessID\"\n:\"\"}"
	err := json.Unmarshal([]byte(tmp), &coupon)
	if err != nil {
		return shim.Error("The parameters passed in are incorrectly formatted")
	}
	err = stub.PutState(coupon.CouponID, []byte(tmp))
	if err != nil {
		return shim.Error(fmt.Sprintf("Coupon %s PutState failed: %s", coupon.CouponID, err.Error()))
	}
	if IsUseEvent {
		err = stub.SetEvent(args[1], []byte{})
		if err != nil {
			return shim.Error(err.Error())
		}
	}
	// 记录一下单个消费者领券信息
	userCoupon, err := stub.GetState("user" + coupon.UserID)
	if err != nil {
		return shim.Error(fmt.Sprintf("get user %s coupon err:%s", coupon.CouponID, err.Error()))
	}
	userCoupon = append(userCoupon, []byte(coupon.CouponID+",")...)
	errPut := stub.PutState("user"+coupon.UserID, userCoupon)
	if errPut != nil {
		return shim.Error(fmt.Sprintf("put user %s coupon error:%s", coupon.CouponID, err.Error()))
	}
	return UpdateCouponNum(stub, coupon.DiscountAmount, "1")
}

// UpdateCouponNum 更新消费券使用情况（主要是数量） 接收三个参数  分别为 stub 、消费券金额、当前要更改的消费券状态
func UpdateCouponNum(stub shim.ChaincodeStubInterface, couponAmount int, status string) pb.Response {
	if status == "1" {
		switch couponAmount {
		case 5:
			Coupon1.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon1)
			err := stub.PutState("coupon5", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon5 Put num failed: %s", err.Error()))
			}
		case 10:
			Coupon2.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon2)
			err := stub.PutState("coupon10", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon10 Put num failed: %s", err.Error()))
			}
		case 20:
			Coupon3.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon3)
			err := stub.PutState("coupon20", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon20 Put num failed: %s", err.Error()))
			}
		case 50:
			Coupon4.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon4)
			err := stub.PutState("coupon50", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon50 Put num failed: %s", err.Error()))
			}
		case 100:
			Coupon5.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon5)
			err := stub.PutState("coupon100", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon100 Put num failed: %s", err.Error()))
			}
		case 200:
			Coupon6.CouponUnused += 1
			Coupon1.CouponNum += 1
			strTmp, _ := json.Marshal(Coupon6)
			err := stub.PutState("coupon200", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon200 Put num failed: %s", err.Error()))
			}
		default:
			return shim.Error("please input right coupon DiscountAmount")

		}
	} else if status == "2" {
		switch couponAmount {
		case 5:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon1)
			err := stub.PutState("coupon5", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon5 Put num failed: %s", err.Error()))
			}
		case 10:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon2)
			err := stub.PutState("coupon10", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon10 Put num failed: %s", err.Error()))
			}
		case 20:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon3)
			err := stub.PutState("coupon20", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon20 Put num failed: %s", err.Error()))
			}
		case 50:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon4)
			err := stub.PutState("coupon50", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon50 Put num failed: %s", err.Error()))
			}
		case 100:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon5)
			err := stub.PutState("coupon100", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon100 Put num failed: %s", err.Error()))
			}
		case 200:
			Coupon1.CouponUnused -= 1
			Coupon1.CouponUsed += 1
			strTmp, _ := json.Marshal(Coupon6)
			err := stub.PutState("coupon200", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon200 Put num failed: %s", err.Error()))
			}
		default:
			return shim.Error("please input right coupon DiscountAmount")

		}
	} else if status == "3" {
		switch couponAmount {
		case 5:
			Coupon1.CouponUsed -= 1
			Coupon1.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon1)
			err := stub.PutState("coupon5", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon5 Put num failed: %s", err.Error()))
			}
		case 10:
			Coupon2.CouponUsed -= 1
			Coupon2.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon2)
			err := stub.PutState("coupon10", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon10 Put num failed: %s", err.Error()))
			}
		case 20:
			Coupon3.CouponUsed -= 1
			Coupon3.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon3)
			err := stub.PutState("coupon20", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon20 Put num failed: %s", err.Error()))
			}
		case 50:
			Coupon4.CouponUsed -= 1
			Coupon4.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon4)
			err := stub.PutState("coupon50", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon50 Put num failed: %s", err.Error()))
			}
		case 100:
			Coupon5.CouponUsed -= 1
			Coupon5.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon5)
			err := stub.PutState("coupon100", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon100 Put num failed: %s", err.Error()))
			}
		case 200:
			Coupon6.CouponUsed -= 1
			Coupon6.CouponEnd += 1
			strTmp, _ := json.Marshal(Coupon6)
			err := stub.PutState("coupon200", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon200 Put num failed: %s", err.Error()))
			}
		default:
			return shim.Error("please input right coupon DiscountAmount")

		}
	} else if status == "4" {
		switch couponAmount {
		case 5:
			Coupon1.CouponTimeOut += 1
			Coupon1.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon1)
			err := stub.PutState("coupon5", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon5 Put num failed: %s", err.Error()))
			}
		case 10:
			Coupon2.CouponTimeOut += 1
			Coupon2.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon2)
			err := stub.PutState("coupon10", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon10 Put num failed: %s", err.Error()))
			}
		case 20:
			Coupon3.CouponTimeOut += 1
			Coupon3.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon3)
			err := stub.PutState("coupon20", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon20 Put num failed: %s", err.Error()))
			}
		case 50:
			Coupon4.CouponTimeOut += 1
			Coupon4.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon4)
			err := stub.PutState("coupon50", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon50 Put num failed: %s", err.Error()))
			}
		case 100:
			Coupon5.CouponTimeOut += 1
			Coupon5.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon5)
			err := stub.PutState("coupon100", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon100 Put num failed: %s", err.Error()))
			}
		case 200:
			Coupon6.CouponTimeOut += 1
			Coupon6.CouponUnused -= 1
			strTmp, _ := json.Marshal(Coupon6)
			err := stub.PutState("coupon200", strTmp)
			if err != nil {
				return shim.Error(fmt.Sprintf("Coupon200 Put num failed: %s", err.Error()))
			}
		default:
			return shim.Error("please input right coupon DiscountAmount")

		}
	}
	return shim.Success(nil)
}

// GetTotalBalance 暂时没有用
func (c *Coupon) GetTotalBalance(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	return shim.Success(nil)
}

//ReceiveCoupon 领取消费券 接收两个参数，args[0]消费券ID args[1]用户的ID args[2]自定义事件ID
// 函数暂时废弃不用
func (c *Coupon) ReceiveCoupon(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	//if len(args) != 3 {
	//	return shim.Error("Incorrect number of arguments. Expecting 2 args to GetCoupon")
	//}
	//coupon, err := stub.GetState(args[0])
	//if err != nil {
	//	return shim.Error("GetCoupon getstate error" + err.Error())
	//}
	//if coupon == nil {
	//	return shim.Error("cann't find the coupon")
	//}
	//var couponOld Coupon
	//json.Unmarshal(coupon, &couponOld)
	//times, err := stub.GetTxTimestamp()
	//if err != nil {
	//	return shim.Error("gettxtimestamp error")
	//}
	//tmpTime := time.Unix(times.Seconds, 0)
	//couponOld.GetCouponTime = tmpTime.Format("2006-01-02")
	//couponOld.UserID = args[1]
	//couponOld.Status = strconv.Itoa(1)
	//couponNew, _ := json.Marshal(couponOld)
	//err = stub.PutState(couponOld.CouponID, couponNew)
	//if err != nil {
	//	return shim.Error("putstate couponNew error")
	//}
	//
	//Str = Str + couponOld.CouponID + ","
	//err = stub.PutState(couponOld.UserID, []byte(Str))
	//if err != nil {
	//	return shim.Error("store user id error")
	//}
	//cc := UpdateCouponNum(stub, couponOld.DiscountAmount, "1")
	//if cc.Status == 500 {
	//	return shim.Error(cc.Message)
	//}
	//
	//if IsUseEvent {
	//	err = stub.SetEvent(args[2], []byte{})
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	}
	//}
	return shim.Success(nil)
}

//UserUnspendCoupon 查询用户未使用消费券  接收一个参数 args[0]用户ID
func (c *Coupon) UserUnspendCoupon(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	coupon, err := stub.GetState("user" + args[0])
	if err != nil {
		return shim.Error("find by userid error")
	}
	if coupon == nil {
		return shim.Error("user is not have any coupons")
	}
	var unspendCoupon []Coupon
	coupons := strings.Split(string(coupon), ",")
	for _, b := range coupons {
		fmt.Println("&&&&&&&&&&&&&", b)
		ss, err := GetCouponByID(stub, b)
		if err != nil {
			return shim.Error("UserUnspendCoupon-----> find by couponid error")
		}
		if ss.Status == "1" {
			unspendCoupon = append(unspendCoupon, ss)
		}
	}
	sxc, _ := json.Marshal(unspendCoupon)
	return shim.Success(sxc)
}

//UserSpendCoupon 查询用户已使用消费券  接收一个参数 args[0]用户ID
func (c *Coupon) UserSpendCoupon(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	coupon, err := stub.GetState("user" + args[0])
	if err != nil {
		return shim.Error("find by userid error")
	}
	if coupon == nil {
		return shim.Error("user is not have any coupons")
	}
	var spendCoupon []Coupon
	coupons := strings.Split(string(coupon), ",")
	for _, b := range coupons {
		ss, err := GetCouponByID(stub, b)
		if err != nil {
			return shim.Error("UserSpendCoupon-----> find by couponid error")
		}
		if ss.Status == "2" {
			spendCoupon = append(spendCoupon, ss)
		}
	}
	sxc, _ := json.Marshal(spendCoupon)
	return shim.Success(sxc)
}

//FindCouponByID 通过消费券ID查询到消费券信息 接收一个参数 args[0]消费券ID
func (c *Coupon) FindCouponByID(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	var couponOld Coupon
	coupon, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("can not find coupon %s by couponID,err:%v", args[0], err))
	}
	if coupon == nil {
		return shim.Error(fmt.Sprintf("coupon %s is null", args[0]))
	}
	err = json.Unmarshal(coupon, &couponOld)
	if err != nil {
		return shim.Error(fmt.Sprintf("coupon %s Unmarshal error:%v", args[0], err))
	}

	return shim.Success(coupon)
}

func GetCouponByID(stub shim.ChaincodeStubInterface, id string) (Coupon, error) {
	var couponOld Coupon
	coupon, err := stub.GetState(id)
	if err != nil {
		return couponOld, fmt.Errorf("can not find coupon %s by couponID,err:%v", id, err)
	}
	if coupon == nil {
		return couponOld, fmt.Errorf("coupon %s is null", id)
	}
	err = json.Unmarshal(coupon, &couponOld)
	if err != nil {
		return couponOld, fmt.Errorf("coupon %s Unmarshal error:%v", id, err)
	}
	return couponOld, nil
}

//UseCoupon 使用消费券 消费券拥有者变为商家   接收两个参数 args[0]消费券ID  args[1]商家ID
func (c *Coupon) UseCoupon(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}
	couponOld, err := GetCouponByID(stub, args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("can not find coupon %s by couponID,err:%v", args[0], err))
	}

	nowTime, _ := stub.GetTxTimestamp()
	tmpTime := time.Unix(nowTime.Seconds, 0)

	couponOld.UsedTime = tmpTime.Format("2006-01-02 03:04:05")
	couponOld.BusinessID = args[1]
	couponOld.Status = strconv.Itoa(2)
	couponNew, _ := json.Marshal(couponOld)
	err = stub.PutState(args[0], couponNew)
	if err != nil {
		return shim.Error(fmt.Sprintf("coupon %s update-putstate error:%v", args[0], err))
	}

	BusinessStr, err := stub.GetState("buiness" + couponOld.BusinessID)
	if err != nil {
		return shim.Error(fmt.Sprintf("get bussiness %s coupon  error:%v", args[1], err))
	}
	BusinessStr = append(BusinessStr, []byte(couponOld.CouponID+",")...)
	err = stub.PutState("buiness"+couponOld.BusinessID, BusinessStr)
	if err != nil {
		return shim.Error("store business id error")
	}
	cc := UpdateCouponNum(stub, couponOld.DiscountAmount, "2")
	if cc.Status == 500 {
		return shim.Error(cc.Message)
	}

	if IsUseEvent {
		err = stub.SetEvent(args[3], []byte{})
		if err != nil {
			return shim.Error(err.Error())
		}
	}
	return shim.Success(couponNew)
}

// GetBuinessCouponInfo 获取商家销核的消费券信息 接收一个参数  BusinessID  返回[]Coupon
func (c *Coupon) GetBuinessCouponInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1 arg to GetBuinessCouponInfo")
	}
	str, err := stub.GetState("buiness" + args[0])
	if err != nil {
		return shim.Error("find business id error")
	}
	if str == nil {
		return shim.Error(fmt.Sprintf("business id %s have no coupon", args[0]))
	}
	var coupons []Coupon
	couponIDs := strings.Split(string(str), ",")
	for _, couponID := range couponIDs {
		coupon, err := GetCouponByID(stub, couponID)
		if err != nil {
			return shim.Error(fmt.Sprintf("GetCouponByID----->can not find coupon %s ,error:%v", couponID, err))
		}
		coupons = append(coupons, coupon)
	}
	scc, _ := json.Marshal(coupons)
	return shim.Success(scc)
}

// SetlemetntWithGov 将来用于商家跟政府部门进行消费券结算  暂未实现
func (c *Coupon) SetlemetntWithGov(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	return shim.Success(nil)
}

//QueryCouponNum 查询消费券的使用情况 接收一个参数
// 参数为存时的ID 即 coupon5 coupon10 coupon20 coupon50 coupon100 coupon200中的一个
// 返回值为CouponCondition序列化后的值
func (c *Coupon) QueryCouponNum(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1 arg to QueryCouponNum")
	}
	str, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("can not find id %s coupon info", args[0]))
	}
	if str == nil {
		return shim.Error(fmt.Sprintf("%s coupon info is null", args[0]))
	}
	var couponNum CouponCondition
	err = json.Unmarshal(str, &couponNum)
	if err != nil {
		return shim.Error("QueryCouponNum---> Unmarshal error")
	}
	return shim.Success(str)
}

func (c *Coupon) UpdateCouponTimeout(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	couponOld, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("get coupon %s info error:%s", args[0], err.Error()))
	}
	var couponNew Coupon
	err = json.Unmarshal(couponOld, &couponNew)
	if err != nil {
		return shim.Error("UpdateCouponTimeout-->Unmarshal error")
	}
	couponNew.Status = "4"
	str, _ := json.Marshal(couponNew)
	err = stub.PutState(couponNew.CouponID, str)
	if err != nil {
		return shim.Error(fmt.Sprintf("put coupon %s after update coupon timeout error:%s", couponNew.CouponID, err.Error()))
	}
	result := UpdateCouponNum(stub, couponNew.DiscountAmount, "4")
	if result.Status == 500 {
		return shim.Error(result.Message)
	}
	return shim.Success(fmt.Sprintf("coupon %s is update timeout success", args[0]))
}

func main() {
	err := shim.Start(new(Coupon))
	if err != nil {
		fmt.Printf("Instantiation of Coupon Failed : %s", err)
	}
}
